#include <mathematics/Frustum.h>

namespace ne
{
    Frustum::Frustum()
    {
        mPlanes[FRUSTUM_PLANE_NEAR] = Plane(Vector3::NEGATIVE_UNIT_Z, 1.0f);
        mPlanes[FRUSTUM_PLANE_FAR] = Plane(Vector3::UNIT_Z, 1000.0f);
        mPlanes[FRUSTUM_PLANE_LEFT] = Plane(Vector3::UNIT_X, 1.0f);
        mPlanes[FRUSTUM_PLANE_RIGHT] = Plane(Vector3::NEGATIVE_UNIT_X, 1.0f);
        mPlanes[FRUSTUM_PLANE_TOP] = Plane(Vector3::NEGATIVE_UNIT_Y, 1.0f);
        mPlanes[FRUSTUM_PLANE_BOTTON] = Plane(Vector3::UNIT_Y, 1.0f);
    }

    Frustum::Frustum(const Frustum &f)
    {
        for (size_t i=0; i<6; ++i)
        {
            mPlanes[i] = f.mPlanes[i];
        }
    }

    void Frustum::setPlane(const Plane &p, const FrustumPlane fp) const
    {
        mPlanes[fp] = p;
    }

    Plane* Frustum::getPlane(const FrustumPlane fp) const
    {
        return &mPlanes[fp];
    }

    bool Frustum::intersects(const AABB &a) const
    {
        for (size_t i=0; i<6; ++i)
        {
            if (mPlanes[i].getSide(a) == Plane::NEGATIVE_SIDE)
            {
                return false;
            }
        }
        return true;
    }

    bool Frustum::intersects(const Sphere &s) const
    {
        for (size_t i=0; i<6; ++i)
        {
            if (mPlanes[i].getSide(s) == Plane::NEGATIVE_SIDE)
            {
                return false;
            }
        }
        return true;
    }

    bool Frustum::intersects(const Vector3 &point) const
    {
        for (size_t i=0; i<6; ++i)
        {
            if (mPlanes[i].getSide(point) == Plane::NEGATIVE_SIDE)
            {
                return false;
            }
        }
        return true;
    }

    Frustum& Frustum::operator = (const Frustum &f)
    {
        for (size_t i=0; i<6; ++i)
        {
            mPlanes[i] = f.mPlanes[i];
        }
        return *this;
    }
}
